import os
from sys import argv

from BeautifulSoup import BeautifulSoup

from urllib2 import urlopen
import re
from datetime import time
import urlparse
from pprint import pprint

import openanything





class Stop:
	def __init__(self, station, time):
		self.station, self.time = station, time
        
class Train:
	def __init__(self, number):
		self.number, self.route = number, []

class MetraParser:
	def __init__(self, source):
		self.data = openanything.fetch(source)["data"]
		soup = BeautifulSoup(self.data)
		#pull out the pre blocks
		pres = map( lambda pre: map(lambda line: str(line), pre.h4.contents), soup.html.findChildren("pre"))
		
		schedule_groups = map(lambda sc: "".join(sc).strip().replace("\r\n", "\n").split("\n") , pres)
		schedules = map(self.__handle_schedule,schedule_groups)
		for schedule in schedules:
			train_numbers, station_stops = schedule
			stations = map(lambda s: s[0], station_stops)
			stops = map(lambda s: s[1], station_stops)
	def __handle_schedule(self, schedule):
		"Take the given schedule group and pull out hte lines and the station times"
		lines = map(lambda line: int(line), schedule.pop(0).split())
		self.line_count =  len(lines)
		station_times = schedule[3:-4]
		station_times = map(lambda line: re.sub("(AR:?)|(LV:?)", "", line), station_times)
		stations = self.__parse_stations(station_times)
		tracks = self.__parse_lines(stations)
		return lines, tracks
		
	def __parse_stations(self,data):
		return [(s.strip(), ts) for s,ts in [(s[:22], s[22:]) for s in data]]

	def __parse_lines(self, data):
		result=[]
		for f,s in data:
			soup = BeautifulSoup(s)
			before_noon, after_noon, before_noon_again = "", "", ""
			if len(soup.contents) == 1:
				if soup.find("b"):
					after_noon = str(soup.b.contents[0])
				else:
					before_noon = str(soup.contents[0])
			elif len(soup.contents) == 2:
				before_noon = str(soup.contents[0])
				after_noon = str(soup.b.contents[0])
			elif len(soup.contents) == 3:
				before_noon = str(soup.contents[0])
				after_noon = str(soup.b.contents[0])
				before_noon_again = str(soup.contents[2])
			else:
				raise RuntimeError, "Expected less than three"
			times = [] + TimeParser(before_noon).times + TimeParser(after_noon, pm=True).times + TimeParser(before_noon_again).times
			assert len(times) == self.line_count, "should have %s stops"%self.line_count
			result.append((f, times))
		return result

class TimeParser:
	def __init__(self, times, pm=False):
		self.times = self.__handle(times, pm)
	def format_time(self, str_time):
		hour, minute = str_time.split(":")
		return time(int(hour), int(minute))
	def __handle(self, times, pm):
		times = times.replace("f", "") #someday handle flag stops
		times = times.replace("            ", " | ").replace("----", "|")
		times =[t != '|' and t or None for t in times.split()] 
		if pm: times = [t and "%s:%s"%( (int(t.split(":")[0]) % 12)+ 12, (t.split(":")[1])) or t for t in times ]
		return [time and self.format_time(time) for time in times]

def build_model(rail_line, inbound, weekday, line_numbers, track_station_stops):
	for idx, train_number in enumerate(line_numbers):
		Train()
		train,n = Train.objects.get_or_create(line=rail_line, number=train_number, in_bound=inbound, weekday=weekday)
		for station_name,stops in track_station_stops:
			station, n = Station.objects.get_or_create(name=station_name)
			time = stops[idx]
			if time:
				print time
				stop, n = Stop.objects.get_or_create(station=station, time=time, train=train)
				train.stops.add(stop)


def main():
	name="Metra Milwaukee District North Line"
	description="Chicago to Fox Lake Suburban Service"
	url = "http://metrarail.com/Sched/md_n/mdn_wko.shtml"
	MetraParser("sample.txt")
#	inbound = False
#	weekday = True
#	groups = MetraParser(data).schedules
#	for group in groups:
#		build_model(rail_line, inbound, weekday, group[0], group[1])
#
if __name__ == "__main__":
	main()
#	
#	url = argv[1]
